#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <curl/curl.h>
#include "json.hpp"
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <filesystem>

using json = nlohmann::json;

// 回调函数，用于处理libcurl下载的数据
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* s) {
    size_t newLength = size * nmemb;
    try {
        s->append((char*)contents, newLength);
    } catch (std::bad_alloc& e) {
        // 处理内存分配失败的情况
        return 0;
    }
    return newLength;
}

// 发送HTTP GET请求并获取响应
std::string httpGet(const std::string& url) {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        }
    }
    return readBuffer;
}

// 将JSON数据保存到文件
void saveJsonToFile(const json& data, const std::string& filename) {
    std::ofstream file(filename, std::ios::out | std::ios::trunc);
    if (file.is_open()) {
        file << data.dump(4); // 格式化输出JSON数据
        file.close();
        std::cout << "JSON数据已成功写入 " << filename << std::endl;
    } else {
        std::cerr << "无法打开文件 " << filename << std::endl;
    }
}

// 加载JSON文件
json loadJsonFromFile(const std::string& filename) {
    std::ifstream file(filename);
    if (file.is_open()) {
        json data;
        file >> data;
        file.close();
        return data;
    } else {
        std::cerr << "无法打开文件 " << filename << std::endl;
        exit(1);
    }
}

// 根据歌曲名称查找相关歌曲
std::vector<std::pair<std::string, std::string>> findSongsByName(const std::string& songName, const json& songsList) {
    std::vector<std::pair<std::string, std::string>> foundSongs;
    for (const auto& song : songsList) {
        if (song["name"].get<std::string>().find(songName) != std::string::npos) {
            foundSongs.emplace_back(song["cid"].get<std::string>(), song["name"].get<std::string>());
        }
    }
    return foundSongs;
}

// 打印歌曲详细信息
void displaySongDetails(const std::string& cid, const std::string& name) {
    std::cout << "CID: " << cid << std::endl;
    std::cout << "名称: " << name << std::endl;
}

// 清理下载链接中的转义字符
std::string cleanDownloadUrl(const std::string& url) {
    std::string cleanedUrl = url;
    boost::algorithm::replace_all(cleanedUrl, "\\u002F", "/");
    return cleanedUrl;
}

// 下载音乐文件
void downloadMusic(const std::string& url, const std::string& savePath) {
    std::string cleanedUrl = cleanDownloadUrl(url);
    std::string response = httpGet(cleanedUrl);
    if (!response.empty()) {
        std::ofstream file(savePath, std::ios::binary);
        if (file.is_open()) {
            file.write(response.c_str(), response.size());
            file.close();
            std::cout << "文件已成功下载并保存到 " << savePath << std::endl;
        } else {
            std::cerr << "无法打开文件 " << savePath << std::endl;
        }
    } else {
        std::cerr << "下载失败" << std::endl;
    }
}

// 打印标题
void printTitle() {
    std::cout << R"(
___________________________________________________________________________
  __  __  ____   _____                            
 |  \/  |/ ___| |  ___|                           
 | |\/| |\___ \ | |_                              
 | |  | | ___) ||  _|____                         
 |_|  |_||____/ |_| |  _ \   ___ __      __ _ __  
                    | | | | / _ \\ \ /\ / /| '_ \ 
Author:Amiya        | |_| || (_) |\ V  V / | | | |
Vision:1.0          |____/  \___/  \_/\_/  |_| |_|
___________________________________________________________________________
)" << std::endl;
}

int main() {
    const std::string url = "https://monster-siren.hypergryph.com/api/songs";
    const std::string filename = "msr.json";

    // 打印标题
    printTitle();

    // 检查是否已存在msr.json文件
    if (!std::filesystem::exists(filename)) {
        std::string response = httpGet(url);
        if (!response.empty()) {
            try {
                json data = json::parse(response);
                saveJsonToFile(data, filename);
            } catch (json::parse_error& e) {
                std::cerr << "JSON解析失败: " << e.what() << std::endl;
                return 1;
            }
        } else {
            std::cerr << "请求失败，未获取到数据" << std::endl;
            return 1;
        }
    }

    // 加载JSON文件
    json data = loadJsonFromFile(filename);
    const json& songsList = data["data"]["list"];

    // 用户输入歌曲名称
    std::string songName;
    std::cout << "请输入歌曲名称或名称中的几个字：";
    std::getline(std::cin, songName);

    // 查找相关歌曲
    auto foundSongs = findSongsByName(songName, songsList);
    if (!foundSongs.empty()) {
        std::cout << "找到与 '" << songName << "' 相关的歌曲：" << std::endl;
        for (size_t i = 0; i < foundSongs.size(); ++i) {
            std::cout << "[" << i + 1 << "] " << foundSongs[i].second << " cid:" << foundSongs[i].first << std::endl;
        }

        // 用户选择歌曲
        int choice;
        std::cout << "请输入编号选择歌曲：";
        std::cin >> choice;
        if (choice >= 1 && choice <= foundSongs.size()) {
            const auto& selectedSong = foundSongs[choice - 1];
            displaySongDetails(selectedSong.first, selectedSong.second);

            // 获取HTML页面并解析下载链接
            std::string htmlUrl = "https://monster-siren.hypergryph.com/music/" + selectedSong.first;
            std::string htmlResponse = httpGet(htmlUrl);
            if (!htmlResponse.empty()) {
                boost::regex pattern("\"sourceUrl\":\"([^\"]+\\.\\w+)\"");
                boost::smatch matches;
                if (boost::regex_search(htmlResponse, matches, pattern)) {
                    std::string downloadUrl = matches[1].str();

                    // 确保music文件夹存在
                    std::filesystem::create_directories("music");

                    // 替换文件名中的非法字符
                    std::string safeName = selectedSong.second;
                    boost::algorithm::replace_all(safeName, " ", "_");
                    std::string savePath = "music/" + safeName + ".mp3";

                    std::cout << "下载地址: " << downloadUrl << std::endl;

        // 下载音乐文件
        downloadMusic(downloadUrl, savePath);
    } else {
        std::cerr << "无法找到下载链接" << std::endl;
    }
} else {
    std::cerr << "请求HTML页面失败" << std::endl;
}

} else {
    std::cerr << "无效的选择" << std::endl;
}

} else {
    std::cerr << "未找到与 '" << songName << "' 相关的歌曲" << std::endl;
}

return 0;